home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / unix-emulation-src / unixfn2FSSpec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-30  |  7.7 KB  |  364 lines  |  [TEXT/EMAC]

  1. /*
  2.  * Copyright (C) 1993, 1994 Marc Parmet.
  3.  * This file is part of the Macintosh port of GNU Emacs.
  4.  *
  5.  * GNU Emacs is distributed in the hope that it will be useful,
  6.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8.  * GNU General Public License for more details.
  9.  */
  10.  
  11. #if defined(THINK_C)
  12. #include <MacHeaders>
  13. #else
  14. #include <Types.h>
  15. #include <Memory.h>
  16. #include <Quickdraw.h>
  17. #include <Windows.h>
  18. #include <TextEdit.h>
  19. #include <Errors.h>
  20. #include <Resources.h>
  21. #endif
  22.  
  23. #include <Aliases.h>
  24. #include "unix-types.h"
  25.  
  26. static struct {
  27.     char *f;
  28.     unsigned char *p[100];
  29.     int n;
  30. } path;
  31.  
  32. static void
  33. colons_to_slashes(char *s,int len)
  34. {
  35.     int i;
  36.     
  37.     for (i = 0; i<len; ++i)
  38.         if (s[i] == ':') s[i] = '/';
  39.     
  40.     if (len > 0 && s[0] == '.') s[0] = '•';
  41. }
  42.  
  43. void
  44. slashes_to_colons(char *s,int len)
  45. {
  46.     int i;
  47.     
  48.     for (i = 0; i<len; ++i)
  49.         if (s[i] == '/') s[i] = ':';
  50.  
  51.     if (len > 0 && s[0] == '•') s[0] = '.';
  52. }
  53.  
  54. static int
  55. slash_at_or_after(int i)
  56. {
  57.     while (1) {
  58.         if (path.f[i] == '\0') return i;
  59.         if (path.f[i] == '/') return i;
  60.         ++i;
  61.     }
  62. }
  63.  
  64. static void
  65. breakup_absolute_unix_pathname(void)
  66. {
  67.     int i,j,last_component;
  68.     
  69.     path.n = 0;
  70.     i = 1;
  71.     last_component = 0;
  72.     while (1) {
  73.         j = slash_at_or_after(i);
  74.         if (i == j) break;
  75.         last_component = (path.f[j] == '\0');
  76.         path.f[j] = '\0';
  77.         path.p[path.n] = (unsigned char *)path.f + i;
  78.         CtoPstr((char *)path.p[path.n]);
  79.         ++path.n;
  80.         if (last_component) break;
  81.         i = j+1;
  82.     }
  83. }
  84.  
  85. static int
  86. find_FSSpec(FSSpec *spec,int stop_at_alias)
  87. {
  88.     int i,err;
  89.     short parent_vRef;
  90.     long parent_dirID;
  91.     Boolean wasAliased,isFolder;
  92.     CInfoPBRec pb;
  93.     HParamBlockRec pb2;
  94.     unsigned char *next_name;
  95.     int at_root;
  96.     unsigned char s[256];
  97.  
  98.     at_root = 1;
  99.     next_name = path.p[i = 0];
  100.  
  101.     while (i < path.n) {
  102.         if (!pstrcmp(next_name,"\p."))
  103.             next_name = path.p[++i];
  104.         else if (!pstrcmp(next_name,"\p..")) {
  105.             if (at_root || parent_dirID == fsRtDirID) {
  106.                 at_root = 1;
  107.                 next_name = path.p[++i];
  108.             }
  109.             else {
  110.                 pb.dirInfo.ioNamePtr = s;
  111.                 pb.dirInfo.ioFDirIndex = -1;
  112.                 pb.dirInfo.ioVRefNum = parent_vRef;
  113.                 pb.dirInfo.ioDrDirID = parent_dirID;
  114.                 err = PBGetCatInfo(&pb,0);
  115.                 if (err) return err;
  116.                 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
  117.                 err = PBGetCatInfo(&pb,0);
  118.                 if (err) return err;
  119.                 err = FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,s,spec);
  120.                 if (err) return err;
  121.                 parent_vRef = pb.dirInfo.ioVRefNum;
  122.                 parent_dirID = pb.dirInfo.ioDrParID;
  123.                 next_name = path.p[++i];
  124.             }
  125.         }
  126.         else {
  127.             pstrcpy(s,next_name);
  128.             colons_to_slashes((char *)s+1,s[0]);
  129.             if (at_root) {
  130.                 pstrcat(s,"\p:");
  131.                 pb2.volumeParam.ioNamePtr = s;
  132.                 pb2.volumeParam.ioVolIndex = -1;
  133.                 pb2.volumeParam.ioVRefNum = 0;
  134.                 err = PBHGetVInfo(&pb2,0);
  135.                 if (err) return err;
  136.                 
  137.                 parent_vRef = pb2.volumeParam.ioVRefNum;
  138.                 parent_dirID = fsRtDirID;
  139.                 err = FSMakeFSSpec(pb2.volumeParam.ioVRefNum,fsRtDirID,0L,spec);
  140.                 if (err) return err;
  141.                 next_name = path.p[++i];
  142.                 at_root = 0;
  143.             }
  144.             else {
  145.                 pb.dirInfo.ioNamePtr = s;
  146.                 pb.dirInfo.ioFDirIndex = 0;
  147.                 pb.dirInfo.ioVRefNum = parent_vRef;
  148.                 pb.dirInfo.ioDrDirID = parent_dirID;
  149.                 err = PBGetCatInfo(&pb,0);
  150.                 if (i == path.n-1 && err == fnfErr) {
  151.                     err = FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrDirID,
  152.                         pb.dirInfo.ioNamePtr,spec);
  153.                     return err;
  154.                 }
  155.                 if (err == fnfErr) return dirNFErr;
  156.                 if (err) return err;
  157.     
  158.                 err = FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,
  159.                                    pb.dirInfo.ioNamePtr,spec);
  160.                 if (err) return err;
  161.                 if (i == path.n-1 && stop_at_alias) break;
  162.                 err = ResolveAliasFile(spec,-1,&isFolder,&wasAliased);
  163.                 if (err) return err;
  164.                 if (wasAliased) {
  165.                     parent_vRef = spec->vRefNum;
  166.                     parent_dirID = spec->parID;
  167.                     next_name = spec->name;
  168.                 }
  169.                 else {
  170.                     parent_vRef = pb.dirInfo.ioVRefNum;
  171.                     parent_dirID = pb.dirInfo.ioDrDirID;
  172.                     next_name = path.p[++i];
  173.                 }
  174.             }
  175.         }
  176.     }
  177.  
  178.     if (at_root) return nsDrvErr;
  179.     return noErr;
  180. }
  181.  
  182. static int
  183. getemacsdir(Handle *u)
  184. {
  185.     int i;
  186.     FCBPBRec pb;
  187.     unsigned char name[256];
  188.     /* Handle rsrc,h; */
  189.     Handle h;
  190.     short err,refNum;
  191.     FSSpec spec;
  192.     static Handle t;
  193.  
  194.     if (t == 0L) {
  195.         /* GetAppParms(name,&refNum,&h); */
  196.         h = GetResource('STR ',128); // Something always available
  197.         if (h == 0L) return resNotFound;
  198.         refNum = HomeResFile(h);
  199.         err = ResError();
  200.         if (err) return err;
  201.         
  202.         pb.ioNamePtr = name;
  203.         pb.ioRefNum = refNum;
  204.         pb.ioFCBIndx = 0;
  205.         err = PBGetFCBInfo(&pb,0);
  206.         if (err) return err;
  207.         err = FSMakeFSSpec(pb.ioFCBVRefNum,pb.ioFCBParID,pb.ioNamePtr,&spec);
  208.         if (err) return err;
  209.         err = FSSpec2unixfn_internal(&spec,&t);
  210.         if (err) return err;
  211.         HLock(t);
  212.         i = strlen(*t) - 1;
  213.         HUnlock(t);
  214.         while (1) {
  215.             if (i == 0) return dirNFErr;
  216.             if ((*t)[i] == '/') break;
  217.             --i;
  218.         }
  219.         (*t)[i+1] = '\0';
  220.     }
  221.  
  222.     HLock(t);
  223.     *u = NewHandle(strlen(*t) + 1);
  224.     err = MemError();
  225.     HUnlock(t);
  226.     if (err) return err;
  227.     HLock(t);
  228.     HLock(*u);
  229.     strcpy(**u,*t);
  230.     HUnlock(t);
  231.     HUnlock(*u);
  232.     return 0;
  233. }
  234.  
  235. static int
  236. based_on_emacs(char *extra1,char *extra2)
  237. {
  238.     int err;
  239.     Handle t;
  240.     
  241.     err = getemacsdir(&t);
  242.     if (err) return err;
  243.     HLock(t);
  244.     path.f = NewPtr(strlen(*t) + strlen(extra1) + strlen(extra2) + 1);
  245.     err = MemError();
  246.     if (err) { DisposHandle(t); return err; }
  247.     strcpy(path.f,*t);
  248.     strcat(path.f,extra1);
  249.     strcat(path.f,extra2);
  250.     DisposHandle(t);
  251.     return 0;
  252. }
  253.  
  254. static int
  255. get_directories(char *t)
  256. {
  257.     short err;
  258.     unsigned char **u = (unsigned char **)GetResource('STR ',128);
  259.     if (err = ResError()) return err;
  260.     HLock((Handle)u);
  261.     pstrcpy((unsigned char *)t,*u);
  262.     HUnlock((Handle)u);
  263.     PtoCstr((unsigned char *)t);
  264.     strcat(t,"/");
  265.     return 0;
  266. }
  267.  
  268. static int
  269. convert_path(FSSpec *fs,int stop_at_alias)
  270. {
  271.     int err;
  272.  
  273.     breakup_absolute_unix_pathname();
  274.     err = find_FSSpec(fs,stop_at_alias);
  275.     DisposPtr(path.f);
  276.     return err;
  277. }
  278.  
  279. int
  280. unixfn2FSSpec_internal(char *s,FSSpec *fs,int stop_at_alias)
  281. {
  282.     int i,err,cwdlen;
  283.     static struct ghost {
  284.         char *false_target,*true_target;
  285.     } ghosts[] = {
  286.         "/tmp",        "",
  287.         "/usr/tmp",    "",
  288.         "/bin",        "etc/",
  289.         "/etc",        "etc/",
  290.         "~emacs",    "",
  291.     };
  292.     static int nghosts = sizeof(ghosts) / sizeof(struct ghost);
  293.     
  294.     if (strlen(s) == 0) return bdNamErr;
  295.  
  296.     for (i = 0; i<nghosts; ++i) {
  297.         if (!strcmp(s,ghosts[i].false_target)) {
  298.             err = based_on_emacs(ghosts[i].true_target,"");
  299.             if (err) return err;
  300.             return convert_path(fs,stop_at_alias);
  301.         }
  302.         else {
  303.             char t[256];
  304.             strcpy(t,ghosts[i].false_target);
  305.             strcat(t,"/");
  306.             if (!strncmp(s,t,strlen(t))) {
  307.                 err = based_on_emacs(ghosts[i].true_target,s + strlen(t));
  308.                 if (err) return err;
  309.                 return convert_path(fs,stop_at_alias);
  310.             }
  311.         }
  312.     }
  313.  
  314.     if (s[0] == '~' && s[1] != '\0') {
  315.         if (!strncmp(s,"~/",2)) {
  316.             char t[256];
  317.             err = get_directories(t);
  318.             if (err) return err;
  319.             strcat(t,"home/");
  320.             err = based_on_emacs(t,s+2);
  321.             if (err) return err;
  322.             err = convert_path(fs,stop_at_alias);
  323.             if (err) {
  324.                 err = based_on_emacs("",s+2);
  325.                 if (err) return err;
  326.                 err = convert_path(fs,stop_at_alias);
  327.                 return err;
  328.             }
  329.             else
  330.                 return noErr;
  331.         }
  332.         else {
  333.             char t[256];
  334.             err = get_directories(t);
  335.             if (err) return err;
  336.             err = based_on_emacs(t,s+1);
  337.             if (err) return err;
  338.             return convert_path(fs,stop_at_alias);
  339.         }
  340.     }
  341.  
  342.     if (s[0] == '/') {
  343.         path.f = NewPtr(strlen(s)+1);
  344.         strcpy(path.f,s);
  345.         return convert_path(fs,stop_at_alias);
  346.     }
  347.     else {
  348.         if (proctable[current_process_index].cwd_string == 0L) return dirNFErr;
  349.         cwdlen = strlen(proctable[current_process_index].cwd_string);
  350.         path.f = NewPtr(strlen(s) + cwdlen + 2);
  351.         strcpy(path.f,proctable[current_process_index].cwd_string);
  352.         if (path.f[cwdlen-1] != '/') strcat(path.f,"/");
  353.         strcat(path.f,s);
  354.         if (path.f[0] == '~') {
  355.             char *g = path.f;
  356.             err = unixfn2FSSpec_internal(g,fs,stop_at_alias);
  357.             DisposPtr(g);
  358.             return err;
  359.         }
  360.         else
  361.             return convert_path(fs,stop_at_alias);
  362.     }
  363. }
  364.